package com.demo;

/*
线程锁
 */
public class Demo6 {
    public static void main(String[] args) throws Exception {
        AddThread add = new AddThread();
        DecThread dec = new DecThread();
        add.start();
        dec.start();
        add.join();
        dec.join();
        System.out.println(Counter.count);
    }
}

class Counter {
    public static final Object lock = new Object();
    public static int count = 0;
}

class AddThread extends Thread {
    public void run() {
        for (int i=0; i<10000; i++) {
            synchronized (Counter.lock) {
                /*
                这里对计数器加1，在操作系统层面其实对应多步操作，包括读取数值、数值运算、存储新数值
                从微观角度这些步骤可能会因为cpu调度切换线程后，分多个时间片执行
                比如两个线程都分别进行了读取数值后再依次进行数值运算，就会导致两个线程的数值运算都是基于原数值的
                如此一来，某个线程的运算操作就丢失了，
                因此synchronized包裹代码块，表示这部分代码内部的操作需要同步执行完毕才能切换到另一个线程
                 */
                Counter.count += 1;
            }
        }
    }
}

class DecThread extends Thread {
    public void run() {
        for (int i=0; i<10000; i++) {
            synchronized (Counter.lock) {
                Counter.count -= 1;
            }
        }
    }
}
